package org.jsola.hr.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.jsola.approval.vo.ApproFlowListVO;
import org.jsola.approval.vo.UserApproListVO;
import org.jsola.approval.vo.UserApproVO;
import org.jsola.common.DateKit8;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.common.HrLogKit;
import org.jsola.hr.constant.*;
import org.jsola.hr.dao.IEmpChangesDAO;
import org.jsola.hr.dto.*;
import org.jsola.hr.dto.excel.EmpChangeImportDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.example.PersonalEventExample;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.provider.IApproProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.EmpChangesQuery;
import org.jsola.hr.query.EmpInfoQuery;
import org.jsola.hr.query.IncreaseDecreaseQuery;
import org.jsola.hr.query.OperationEmpRecordQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.service.excel.EmpChangeImportListener;
import org.jsola.hr.task.SendNoticeTask;
import org.jsola.hr.vo.*;
import org.jsola.hr.vo.excel.ParseResultVO;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.EmpInfoStatus.WAIT_QUIT;
import static org.jsola.hr.constant.EmpSocConstant.NO_CONFIRM;
import static org.jsola.hr.constant.HrPermissionConstants.SYSTEM_SUBJECT_TYPE;

/**
 * @author zhr
 */
@Slf4j
@Service("hrEmpChangesServiceImpl")
public class EmpChangesServiceImpl implements IEmpChangesService {

    @Autowired
    private IEmpChangesDAO empChangesDAO;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpDepService empDepService;

    @Autowired
    private IEmpPositionService empPositionService;

    @Autowired
    private IApproProviderService approProviderService;

    @Autowired
    private IPersonalEventService personalEventService;

    @Autowired
    private IEmpSocMonthService empSocMonthService;

    @Autowired
    private ICheckInPeopleService checkInPeopleService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private IEmpSocPlanService empSocPlanService;

    @Autowired
    private IEmpSocInfoService empSocInfoService;

    @Autowired
    private IOperationEmpRecordService operationEmpRecordService;

    @Autowired
    private SendNoticeTask sendNoticeTask;

    @Autowired
    private IEmpSocInfoExtraService empSocInfoExtraService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpChangesVO save(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        // 转DO
        EmpChangesDO empChangesDO = empChangesAddDTO.to(EmpChangesDO.class);

        if (empChangesDO.getChangeStatus() == null) {
            empChangesDO.setChangeStatus(EmpChangeStatus.INIT.getValue());
        }
        // 保存
        empChangesDO = save(empChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empChangesDO.to(EmpChangesVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpChangesUpdateDTO empChangesUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpChangesDO empChangesDO = empChangesUpdateDTO.to(EmpChangesDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empChangesIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empChangesIds);
    }


    @Override
    public EmpChangesVO selectById(String empChangesId, String siteId) {
        EmpChangesDO empChangesDO = selectDOById(empChangesId, siteId);
        if (empChangesDO == null) {
            return null;
        }
        return empChangesDO.to(EmpChangesVO.class);
    }

    @Override
    public List<EmpChangesDO> selectByIdList(List<String> empChangesIdList) {
        if (CollectionUtils.isEmpty(empChangesIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("id", empChangesIdList);
        return empChangesDAO.selectByExample(example);
    }

    @Override
    public List<EmpChangesListVO> select(EmpChangesQuery empChangesQuery, String siteId) {
        List<EmpChangesDO> empChangesDOList = selectDO(empChangesQuery, siteId);
        if (CollectionUtils.isEmpty(empChangesDOList)) {
            return empChangesDOList == null ? null : new ArrayList<>();
        }
        return empChangesDOList.stream()
                .map(empChangesDO -> empChangesDO.to(EmpChangesListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpChangesQuery empChangesQuery, String siteId) {
        Example example = buildExample(empChangesQuery, siteId);
        return empChangesDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpChangesListVO> selectPage(EmpChangesQuery empChangesQuery, String siteId) {
        Example example = buildExample(empChangesQuery, siteId);
        Page<EmpChangesDO> page = empChangesDAO.selectPageByExample(example,
                empChangesQuery.getPageNo(),
                empChangesQuery.getPageSize());

        return page.to(EmpChangesListVO.class);
    }

    @Override
    public EmpChangesDO selectDOById(String empChangesId, String siteId) {
        return listById(empChangesId, siteId);
    }

    @Override
    public List<EmpChangesDO> selectDO(EmpChangesQuery empChangesQuery, String siteId) {
        Example example = buildExample(empChangesQuery, siteId);
        return empChangesDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param empChangesQuery 查询参数
     * @param siteId          所属站点id
     * @return example
     */
    private Example buildExample(EmpChangesQuery empChangesQuery, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empChangesQuery.getEmpId() != null) {
            example.and().andLike("empId", "%" + empChangesQuery.getEmpId() + "%");
        }
        if (empChangesQuery.getApproFlowId() != null) {
            example.and().andEqualTo("approFlowId", empChangesQuery.getApproFlowId());
        }
        if (empChangesQuery.getUserApproFlowId() != null) {
            example.and().andEqualTo("userApproFlowId", empChangesQuery.getUserApproFlowId());
        }
        if (empChangesQuery.getChangeType() != null) {
            example.and().andEqualTo("changeType", empChangesQuery.getChangeType());
        }
        if (empChangesQuery.getPreCode() != null) {
            example.and().andLike("preCode", "%" + empChangesQuery.getPreCode() + "%");
        }
        if (empChangesQuery.getCurrentCode() != null) {
            example.and().andLike("currentCode", "%" + empChangesQuery.getCurrentCode() + "%");
        }
        if (empChangesQuery.getFormallyDateStart() != null &&
                empChangesQuery.getFormallyDateEnd() != null) {
            example.and().andBetween("formallyDate", empChangesQuery.getFormallyDateStart(),
                    empChangesQuery.getFormallyDateEnd());
        }
        if (empChangesQuery.getProbationDateStart() != null &&
                empChangesQuery.getProbationDateEnd() != null) {
            example.and().andBetween("probationDate", empChangesQuery.getProbationDateStart(),
                    empChangesQuery.getProbationDateEnd());
        }
        if (empChangesQuery.getRegularDateStart() != null &&
                empChangesQuery.getRegularDateEnd() != null) {
            example.and().andBetween("regularDate", empChangesQuery.getRegularDateStart(),
                    empChangesQuery.getRegularDateEnd());
        }
        if (empChangesQuery.getRegularEvaluation() != null) {
            example.and().andLike("regularEvaluation", "%" + empChangesQuery.getRegularEvaluation() + "%");
        }
        if (empChangesQuery.getRegularAttacment() != null) {
            example.and().andLike("regularAttacment", "%" + empChangesQuery.getRegularAttacment() + "%");
        }
        if (empChangesQuery.getAdjustmentDateStart() != null &&
                empChangesQuery.getAdjustmentDateEnd() != null) {
            example.and().andBetween("adjustmentDate", DateKit8.getStartTime(empChangesQuery.getAdjustmentDateStart()),
                    DateKit8.getEndTime(empChangesQuery.getAdjustmentDateEnd()));
        }
        if (empChangesQuery.getAdjustmentReason() != null) {
            example.and().andLike("adjustmentReason", "%" + empChangesQuery.getAdjustmentReason() + "%");
        }
        if (empChangesQuery.getAdjustmentAttachment() != null) {
            example.and().andLike("adjustmentAttachment", "%" + empChangesQuery.getAdjustmentAttachment() + "%");
        }
        if (empChangesQuery.getPreDep() != null) {
            example.and().andLike("preDep", "%" + empChangesQuery.getPreDep() + "%");
        }
        if (empChangesQuery.getPrePosition() != null) {
            example.and().andLike("prePosition", "%" + empChangesQuery.getPrePosition() + "%");
        }
        if (empChangesQuery.getPreLevel() != null) {
            example.and().andEqualTo("preLevel", empChangesQuery.getPreLevel());
        }
        if (empChangesQuery.getPreSupervisor() != null) {
            example.and().andLike("preSupervisor", "%" + empChangesQuery.getPreSupervisor() + "%");
        }
        if (empChangesQuery.getPreManagerForm() != null) {
            example.and().andEqualTo("preManagerForm", empChangesQuery.getPreManagerForm());
        }
        if (empChangesQuery.getPreWorkCityId() != null) {
            example.and().andLike("preWorkCityId", "%" + empChangesQuery.getPreWorkCityId() + "%");
        }
        if (empChangesQuery.getCurrentDep() != null) {
            example.and().andLike("currentDep", "%" + empChangesQuery.getCurrentDep() + "%");
        }
        if (empChangesQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empChangesQuery.getCompanyId());
        }
        if (empChangesQuery.getCurrentPosition() != null) {
            example.and().andLike("currentPosition", "%" + empChangesQuery.getCurrentPosition() + "%");
        }
        if (empChangesQuery.getCurrentLevel() != null) {
            example.and().andEqualTo("currentLevel", empChangesQuery.getCurrentLevel());
        }
        if (empChangesQuery.getCurrentSupervisor() != null) {
            example.and().andLike("currentSupervisor", "%" + empChangesQuery.getCurrentSupervisor() + "%");
        }
        if (empChangesQuery.getCurrentManagerForm() != null) {
            example.and().andEqualTo("currentManagerForm", empChangesQuery.getCurrentManagerForm());
        }
        if (empChangesQuery.getCurrentWorkCityId() != null) {
            example.and().andLike("currentWorkCityId", "%" + empChangesQuery.getCurrentWorkCityId() + "%");
        }
        if (empChangesQuery.getQuitType() != null) {
            example.and().andEqualTo("quitType", empChangesQuery.getQuitType());
        }
        if (empChangesQuery.getQuitDateStart() != null &&
                empChangesQuery.getQuitDateEnd() != null) {
            example.and().andBetween("quitDate", empChangesQuery.getQuitDateStart(),
                    empChangesQuery.getQuitDateEnd());
        }
        if (empChangesQuery.getPreQuitDateStart() != null &&
                empChangesQuery.getPreQuitDateEnd() != null) {
            example.and().andBetween("preQuitDate", DateKit8.getStartTime(empChangesQuery.getPreQuitDateStart()),
                    DateKit8.getEndTime(empChangesQuery.getPreQuitDateEnd()));
        }
        if (empChangesQuery.getHandleQuitDateStart() != null &&
                empChangesQuery.getHandleQuitDateEnd() != null) {
            example.and().andBetween("handleQuitDate", empChangesQuery.getHandleQuitDateStart(),
                    empChangesQuery.getHandleQuitDateEnd());
        }
        if (empChangesQuery.getPersonalReason() != null) {
            example.and().andEqualTo("personalReason", empChangesQuery.getPersonalReason());
        }
        if (empChangesQuery.getCompanyReason() != null) {
            example.and().andEqualTo("companyReason", empChangesQuery.getCompanyReason());
        }
        if (empChangesQuery.getQuitReason() != null) {
            example.and().andLike("quitReason", "%" + empChangesQuery.getQuitReason() + "%");
        }
        if (empChangesQuery.getQuitRemarks() != null) {
            example.and().andEqualTo("quitRemarks", empChangesQuery.getQuitRemarks());
        }
        if (empChangesQuery.getApplyQuitReason() != null) {
            example.and().andLike("applyQuitReason", "%" + empChangesQuery.getApplyQuitReason() + "%");
        }
        if (empChangesQuery.getCompensationStart() != null &&
                empChangesQuery.getCompensationEnd() != null) {
            example.and().andBetween("compensation", empChangesQuery.getCompensationStart(),
                    empChangesQuery.getCompensationEnd());
        }
        if (empChangesQuery.getPaymentLieuNoticeStart() != null &&
                empChangesQuery.getPaymentLieuNoticeEnd() != null) {
            example.and().andBetween("paymentLieuNotice", empChangesQuery.getPaymentLieuNoticeStart(),
                    empChangesQuery.getPaymentLieuNoticeEnd());
        }
        if (empChangesQuery.getSsAttritionMonthStart() != null &&
                empChangesQuery.getSsAttritionMonthEnd() != null) {
            example.and().andBetween("ssAttritionMonth", empChangesQuery.getSsAttritionMonthStart(),
                    empChangesQuery.getSsAttritionMonthEnd());
        }
        if (empChangesQuery.getPfAttritionMonthStart() != null &&
                empChangesQuery.getPfAttritionMonthEnd() != null) {
            example.and().andBetween("pfAttritionMonth", empChangesQuery.getPfAttritionMonthStart(),
                    empChangesQuery.getPfAttritionMonthEnd());
        }
        if (empChangesQuery.getSurplusYearHoliday() != null) {
            example.and().andEqualTo("surplusYearHoliday", empChangesQuery.getSurplusYearHoliday());
        }
        if (empChangesQuery.getSurplusBreakOff() != null) {
            example.and().andEqualTo("surplusBreakOff", empChangesQuery.getSurplusBreakOff());
        }
        if (empChangesQuery.getDirectlyUnderNumber() != null) {
            example.and().andEqualTo("directlyUnderNumber", empChangesQuery.getDirectlyUnderNumber());
        }
        if (empChangesQuery.getChangeStatus() != null) {
            example.and().andEqualTo("changeStatus", empChangesQuery.getChangeStatus());
        }
        if (empChangesQuery.getGmtCreateStart() != null &&
                empChangesQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", empChangesQuery.getGmtCreateStart(),
                    empChangesQuery.getGmtCreateEnd());
        }
        if (empChangesQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + empChangesQuery.getCreateUserId() + "%");
        }
        if (empChangesQuery.getGmtModifiedStart() != null &&
                empChangesQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", empChangesQuery.getGmtModifiedStart(),
                    empChangesQuery.getGmtModifiedEnd());
        }
        if (empChangesQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + empChangesQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example, empChangesQuery.getOrders());
        return example;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpChangesVO transferFormal(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        // 转DO
        EmpChangesDO empChangesDO = empChangesAddDTO.to(EmpChangesDO.class);
        empChangesDO.setChangeStatus(EmpChangeStatus.PASS.getValue());
        empChangesDO.setChangeType(EmpChangeType.TRANSFER__FORMAL.getValue());
        // 保存
        empChangesDO = save(empChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesAddDTO.getEmpId());
        empInfoUpdateDTO.setEmployType(true);
        empInfoUpdateDTO.setFormalType(1);
        if (StringUtils.isNotBlank(empChangesAddDTO.getCurrentCode())) {
            empInfoUpdateDTO.setNumber(empChangesAddDTO.getCurrentCode());
        }
        empInfoService.update(empInfoUpdateDTO, tokenUser);
        return empChangesDO.to(EmpChangesVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void batchTransferRegular(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        for (String empId : empChangesAddDTO.getEmpIdS()) {
            empChangesAddDTO.setEmpId(empId);
            transferRegular(empChangesAddDTO, tokenUser);
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpChangesVO transferRegular(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {

        // 员工信息
        EmpInfoVO empInfoVO = getEmpInfoByEmpId(empChangesAddDTO.getEmpId(), tokenUser.getSiteId());

        // 转DO
        EmpChangesDO empChangesDO = empChangesAddDTO.to(EmpChangesDO.class);
        // 转正日期
        if (empChangesDO.getRegularDate() == null) {
            empChangesDO.setRegularDate(new Date());
        }
        empChangesDO.setChangeStatus(EmpChangeStatus.PASS.getValue());
        empChangesDO.setChangeType(EmpChangeType.TRANSFER__REGULAR.getValue());
        // 保存
        empChangesDO = save(empChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
        // 转vo
        EmpChangesVO empChangesVO = empChangesDO.to(EmpChangesVO.class);

        // 获取明天时间0点
        Date dateTomorrow = DateUtils.getTomorrow();
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesAddDTO.getEmpId());
        empInfoUpdateDTO.setTurnStraightDate(empChangesDO.getRegularDate());
        empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());

        // 转正时间明天之前,直接转正
        if (empChangesDO.getRegularDate().before(dateTomorrow)) {
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO.setChangeStatus(0);
            // 正式类型（1：试用期，2：已转正）
            empInfoUpdateDTO.setFormalType(2);
        } else {
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO.setChangeStatus(1);
            // 正式类型（1：试用期，2：已转正）
            empInfoUpdateDTO.setFormalType(1);
            // 入职时间今天之后,转正日期当天转为正式员工
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        }

        empInfoService.update(empInfoUpdateDTO, tokenUser);
        String desc = PersonalEventEnum.REGULAR_WORKER.getDesc();
        personalEventService.autoSave(empInfoVO, tokenUser, desc, PersonalEventEnum.REGULAR_WORKER.getValue(), PersonalEventEnum.REGULAR_WORKER.getDesc());

        // 操作日志
        HrLogKit.logForSave("员工申请转正,员工姓名:" + empInfoVO.getName(), "transferRegular",
                empChangesVO.getId(), empInfoVO.getCompanyId(), tokenUser);

        // 是否走审批
        // 获取转正审批
        List<ApproFlowListVO> approFlowList = approProviderService.listTurnStraightCanUseFlowsByCompany(empChangesAddDTO.getCompanyId(), tokenUser);
        if (CollectionUtils.isEmpty(approFlowList)) {
            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO1 = new EmpInfoUpdateDTO();
            empInfoUpdateDTO1.setId(empChangesAddDTO.getEmpId());
            empInfoUpdateDTO1.setTurnStraightDate(empChangesDO.getRegularDate());
            empInfoUpdateDTO1.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());

            // 转正时间明天之前,直接转正
            if (empChangesDO.getRegularDate().before(dateTomorrow)) {
                // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                empInfoUpdateDTO1.setChangeStatus(0);
                // 正式类型（1：试用期，2：已转正）
                empInfoUpdateDTO1.setFormalType(2);
            } else {
                // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                empInfoUpdateDTO1.setChangeStatus(1);
                // 正式类型（1：试用期，2：已转正）
                empInfoUpdateDTO1.setFormalType(1);
                // 入职时间今天之后,转正日期当天转为正式员工
                empInfoUpdateDTO1.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
            }

            empInfoService.update(empInfoUpdateDTO1, tokenUser);
            HrLogKit.logForSave("员工申请转正:" + empInfoVO.getName(), "transferRegular", empChangesVO.getId(), tokenUser);
        } else {
            // 走转正审批
            String approFlowId = empChangesAddDTO.getApproFlowId();

            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO1 = new EmpInfoUpdateDTO();
            empInfoUpdateDTO1.setId(empChangesAddDTO.getEmpId());
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO1.setChangeStatus(1);
            // 待审批
            empInfoUpdateDTO1.setApprovalStatus(ApprovalStatusEnum.APPRO_ING.getValue());

            // 发起转正审批
            UserApproVO userApproVO = approProviderService.createTurnStraightAppro(empInfoVO, empChangesVO, approFlowId, tokenUser);
            // 保存审批用的流程
            updateUserApproId(empChangesVO.getId(), userApproVO.getId(), userApproVO.getFlowId(), tokenUser);
            // 修改员工信息
            empInfoService.update(empInfoUpdateDTO1, tokenUser);
            HrLogKit.logForSave("员工发起转正审批:" + empInfoVO.getName(), "transferRegularAppro", userApproVO.getId(), tokenUser);
            HrLogKit.logForSave("员工申请转正:" + empInfoVO.getName(), "transferRegular", empChangesVO.getId(), tokenUser);
        }

        return empChangesVO;
    }

    /**
     * 根据员工id获取员工信息
     *
     * @param empId  员工id
     * @param siteId 站点id
     * @return 员工信息
     */
    private EmpInfoVO getEmpInfoByEmpId(String empId, String siteId) {
        EmpInfoVO empInfoVO = empInfoService.selectById(empId, siteId);
        if (Objects.isNull(empInfoVO)) {
            throw new HrException("待转正员工信息不存在或已删除");
        }
        return empInfoVO;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void batchTransferPosition(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        ParamException.notEmpty(empChangesAddDTO.getEmpIdS(), "请传入员工id");
        List<EmpChangesVO> empChangesVOList = new ArrayList<>();
        for (String empId : empChangesAddDTO.getEmpIdS()) {
            empChangesAddDTO.setEmpId(empId);
            empChangesAddDTO.setUpdateType(1);
            EmpChangesVO empChangesVO = transferPosition(empChangesAddDTO, tokenUser);
            empChangesVOList.add(empChangesVO);
        }
        if (!CollectionUtils.isEmpty(empChangesVOList)) {
            String subjectId = empChangesVOList.stream().map(EmpChangesVO::getId).collect(Collectors.joining(","));
            sendNotice(subjectId, empChangesAddDTO.getCompanyId(), empChangesAddDTO.getAdjustmentDate(), NoticeConstants.PRE_TRANSFER, tokenUser);
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpChangesVO transferPosition(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        // 员工信息
        EmpInfoVO empInfoVO = getEmpInfoByEmpId(empChangesAddDTO.getEmpId(), tokenUser.getSiteId());
        CompanyDO companyDO = companyService.selectDOById(empInfoVO.getCompanyId(), tokenUser.getSiteId());
        //原部门
        List<EmpDepDO> empDepDOList = empDepService.listAllByEmpId(empChangesAddDTO.getCompanyId(),
                empChangesAddDTO.getEmpId(),
                tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(empDepDOList)) {
            StringJoiner stringJoiner = new StringJoiner(",");
            for (EmpDepDO empDepDO : empDepDOList) {
                stringJoiner.add(empDepDO.getDepId());
            }
            empChangesAddDTO.setPreDep(stringJoiner.toString());
        }
        // 要转的部门
        if (StringUtils.isEmpty(empChangesAddDTO.getCurrentDep()) &&
                !CollectionUtils.isEmpty(empChangesAddDTO.getCurrentDepIdList())) {
            String depIds = String.join(",", empChangesAddDTO.getCurrentDepIdList());
            empChangesAddDTO.setCurrentDep(depIds);
        }
        if (!StringUtils.isEmpty(empChangesAddDTO.getCurrentDep()) &&
                CollectionUtils.isEmpty(empChangesAddDTO.getCurrentDepIdList())) {
            List<String> depIdList = Arrays.asList(empChangesAddDTO.getCurrentDep().split(","));
            empChangesAddDTO.setCurrentDepIdList(depIdList);
        }
        //原岗位
        List<EmpPositionDO> empPositionDOList = empPositionService.listAllByEmpId(empChangesAddDTO.getCompanyId(),
                empChangesAddDTO.getEmpId(),
                tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(empPositionDOList)) {
            StringJoiner stringJoiner = new StringJoiner(",");
            for (EmpPositionDO empPositionDO : empPositionDOList) {
                stringJoiner.add(empPositionDO.getPositionId());
            }
            empChangesAddDTO.setPrePosition(stringJoiner.toString());
        }
        // 要转的岗位
        if (StringUtils.isEmpty(empChangesAddDTO.getCurrentPosition()) &&
                !CollectionUtils.isEmpty(empChangesAddDTO.getCurrentPositionIdList())) {
            String positionIds = String.join(",", empChangesAddDTO.getCurrentPositionIdList());
            empChangesAddDTO.setCurrentPosition(positionIds);
        }
        if (!StringUtils.isEmpty(empChangesAddDTO.getCurrentPosition()) &&
                CollectionUtils.isEmpty(empChangesAddDTO.getCurrentPositionIdList())) {
            List<String> positionIdList = Arrays.asList(empChangesAddDTO.getCurrentPosition().split(","));
            empChangesAddDTO.setCurrentPositionIdList(positionIdList);
        }

        empChangesAddDTO.setChangeType(EmpChangeType.TRANSFER__POSITION.getValue());
        // 保存
        EmpChangesVO empChangesVO = save(empChangesAddDTO, tokenUser);

        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesAddDTO.getEmpId());
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(2);

        // 是否走审批
        // 获取调岗审批
        List<ApproFlowListVO> approFlowList = approProviderService.listTransferDutyCanUseFlowsByCompany(empChangesAddDTO.getCompanyId(), tokenUser);
        if (CollectionUtils.isEmpty(approFlowList)) {
            // 不需要审批
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
            // 调岗待调岗发通知
            if (empChangesAddDTO.getChangeType() != null) {
                if (empChangesAddDTO.getChangeType() == 1) {
                    sendNotice(empChangesVO.getId(), empInfoVO.getCompanyId(), empChangesAddDTO.getAdjustmentDate(), NoticeConstants.PRE_TRANSFER, tokenUser);
                }
            }
        } else {
            // 走调岗审批
            String approFlowId = empChangesAddDTO.getApproFlowId();
            // 待审批
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_ING.getValue());

            // 发起调岗审批
            UserApproVO userApproVO = approProviderService.createTransferDutyAppro(empInfoVO, empChangesVO, approFlowId, tokenUser);
            // 保存审批用的流程
            updateUserApproId(empChangesVO.getId(), userApproVO.getId(), userApproVO.getFlowId(), tokenUser);

            HrLogKit.logForSave("员工发起调岗审批,员工姓名:" + empInfoVO.getName(), "transferPositionAppro",
                    userApproVO.getId(), companyDO.getId(), tokenUser);
        }
        // 修改员工信息

        empInfoService.update(empInfoUpdateDTO, tokenUser);

        HrLogKit.logForSave("员工申请调岗,员工姓名:" + empInfoVO.getName(), "transferPosition",
                empChangesVO.getId(), companyDO.getId(), tokenUser);
        EmpInfoQuery empInfoQuery = new EmpInfoQuery();
        empInfoQuery.setId(empChangesVO.getEmpId());
        empInfoQuery.setCompanyId(empChangesVO.getCompanyId());
        Page<EmpInfoListVO> empInfoListVOPage = empInfoService.selectEmpInfoTransferRelation(empInfoQuery, tokenUser);
        List<EmpInfoListVO> entities = empInfoListVOPage.getEntities();

        EmpChangesListVO empChangesListVO = entities.parallelStream()
                .filter(empInfoListVO -> empInfoListVO.getId().equals(empChangesVO.getEmpId()))
                .map(EmpInfoListVO::getEmpChangesListVO)
                .findFirst().orElse(null);
        StringBuilder desc = new StringBuilder();
        if (empChangesListVO != null) {
            desc.append(PersonalEventExample.INSERT_INTO_ADMIN).append(tokenUser.getUserName());
            desc.append(PersonalEventExample.INSERT_TRANSFER + ",");
            desc.append(PersonalEventExample.INSERT_TRANSFER_DEPT).append(empChangesListVO.getCurrentDepName()).append(",");
            desc.append(PersonalEventExample.INSERT_TRANSFER_POSITION).append(empChangesListVO.getCurrentPositionName()).append(",");
            String dateStr = DateFormatUtils.format(empChangesVO.getAdjustmentDate() != null ? empChangesVO.getAdjustmentDate() : new Date(), "yyyy-MM-dd");

            desc.append(PersonalEventExample.INSERT_TRANSFER_PRETRANSFER).append(dateStr);
        }

        if (StringUtils.isNoneEmpty(empChangesVO.getAdjustmentReason())) {
            desc.append(PersonalEventExample.INSERT_TRANSFER_REASON).append(empChangesVO.getAdjustmentReason());
        }
        personalEventService.autoSave(empInfoVO, tokenUser, desc.toString(), PersonalEventEnum.TRANSFER_PROCEDURE.getValue(), PersonalEventEnum.TRANSFER_PROCEDURE.getDesc());

        return empChangesVO;
    }

    /**
     * 待调岗员工发通知
     *
     * @param subjectId      业务id（待调岗：hr_emp_changes表id; 待离职：hr_emp_changes表id; 离职：hr_emp_info表id）
     * @param noticeDate     通知时间
     * @param noticeTypeCode 通知类型code
     * @param tokenUser      当前用户
     */
    @Override
    public void sendNotice(String subjectId, String companyId, Date noticeDate, String noticeTypeCode, TokenUser tokenUser) {
        try {
            //员工变动id获得员工id
            String[] ids = subjectId.split(",");
            EmpChangesVO empChangesVO = selectById(ids[0], tokenUser.getSiteId());
            if ((empChangesVO == null || StringUtils.isEmpty(empChangesVO.getId())) && !NoticeConstants.RESIGN.equals(noticeTypeCode)) {
                log.error("发送通知失败，找不到员工变动记录");
                return;
            }
            if (NoticeConstants.PRE_TRANSFER.equals(noticeTypeCode)) {
                //没有待调岗审批才发送通知
                List<UserApproListVO> userApproListVOS = empInfoService.empApproList(empChangesVO.getEmpId(), HrConstants.APPROVE_TRANSFER_DUTY, tokenUser);
                if (CollectionUtils.isEmpty(userApproListVOS)) {
                    sendNoticeTask.addTask(subjectId, noticeTypeCode, companyId, noticeDate,
                            "人员待调岗发送通知", tokenUser);
                }

            } else if (NoticeConstants.PRE_RESIGN.equals(noticeTypeCode)) {
                //没有待离职审批才发送通知
                List<UserApproListVO> userApproListVOS = empInfoService.empApproList(empChangesVO.getEmpId(), HrConstants.APPROVE_LEAVING, tokenUser);
                if (CollectionUtils.isEmpty(userApproListVOS)) {
                    sendNoticeTask.addTask(subjectId, noticeTypeCode, companyId, noticeDate,
                            "人员待离职发送通知", tokenUser);
                }

            } else if (NoticeConstants.RESIGN.equals(noticeTypeCode)) {
                sendNoticeTask.addTask(subjectId, noticeTypeCode, companyId, noticeDate,
                        "人员离职发送通知", tokenUser);
            }
        } catch (Exception e) {
            log.error("待调岗员工发通知失败，错误信息：{}", e.getMessage());
        }
    }

    /**
     * 更新用户所用审批
     *
     * @param empChangesId 员工改变id
     * @param userApproId  用户审批id
     * @param flowId       审批id
     * @param tokenUser    当前用户
     */
    private void updateUserApproId(String empChangesId, String userApproId, String flowId, TokenUser tokenUser) {

        EmpChangesDO empChangesDO = new EmpChangesDO();
        empChangesDO.setId(empChangesId);
        empChangesDO.setUserApproFlowId(userApproId);
        empChangesDO.setApproFlowId(flowId);
        //根据主键更新，只更新非null值
        updateByIdSelective(empChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    /**
     * 调岗修改部门/岗位
     *
     * @param empChangesVO          修改记录
     * @param currentDepIdList      要调入的部门List
     * @param currentPositionIdList 要调入的岗位List
     * @param tokenUser             当前用户
     */
    private void updateDepAndPositionInfo(EmpChangesVO empChangesVO, List<String> currentDepIdList, List<String> currentPositionIdList, TokenUser tokenUser) {
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
        if (!StringUtils.isEmpty(empChangesVO.getCurrentDep()) ||
                !CollectionUtils.isEmpty(currentDepIdList)) {
            // 原部门
            empDepService.deleteByEmpDep(empChangesVO.getCompanyId(), empChangesVO.getEmpId(), empChangesVO.getPreDep(), tokenUser);
            // 新部门
            List<String> depIdList = currentDepIdList;
            if (CollectionUtils.isEmpty(currentDepIdList)) {
                depIdList = new ArrayList<>();
                depIdList.add(empChangesVO.getCurrentDep());
            }
            empInfoDO.setPreJoinDep(String.join(",", currentDepIdList));
            // 保存员工的部门
            empDepService.saveEmpDeps(empChangesVO.getCompanyId(), empChangesVO.getEmpId(), depIdList, tokenUser);
        }

        if (!StringUtils.isEmpty(empChangesVO.getCurrentPosition()) ||
                !CollectionUtils.isEmpty(currentPositionIdList)) {
            // 原岗位
            empPositionService.deleteByEmpPosition(empChangesVO.getCompanyId(), empChangesVO.getEmpId(), empChangesVO.getPrePosition(), tokenUser);
            // 新岗位
            if (CollectionUtils.isEmpty(currentPositionIdList)) {
                currentPositionIdList = new ArrayList<>();
                currentPositionIdList.add(empChangesVO.getCurrentPosition());
            }
            empInfoDO.setPreJoinPosition(String.join(",", currentPositionIdList));
            // 保存员工的岗位
            empPositionService.saveEmpPositions(empChangesVO.getCompanyId(), empChangesVO.getEmpId(), currentPositionIdList, tokenUser);
        }
        empInfoService.updateByIdSelective(empInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void batchLeavePosition(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {
        List<EmpChangesVO> empChangesVOList = new ArrayList<>();
        for (String empId : empChangesAddDTO.getEmpIdS()) {
            empChangesAddDTO.setEmpId(empId);
            EmpChangesVO empChangesVO = leavePosition(empChangesAddDTO, tokenUser);
            empChangesVOList.add(empChangesVO);
        }
        // 发送待离职通知
        if (!CollectionUtils.isEmpty(empChangesVOList)) {
            String subjectId = empChangesVOList.stream().map(EmpChangesVO::getId).collect(Collectors.joining(","));
            sendNotice(subjectId, empChangesAddDTO.getCompanyId(), empChangesAddDTO.getPreQuitDate(), NoticeConstants.PRE_RESIGN, tokenUser);
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpChangesVO leavePosition(EmpChangesAddDTO empChangesAddDTO, TokenUser tokenUser) {

        // 员工信息
        EmpInfoVO empInfoVO = getEmpInfoByEmpId(empChangesAddDTO.getEmpId(), tokenUser.getSiteId());
        CompanyDO companyDO = companyService.selectDOById(empInfoVO.getCompanyId(), tokenUser.getSiteId());
        empChangesAddDTO.setChangeType(EmpChangeType.LEAVE.getValue());
        // 保存
        EmpChangesVO empChangesVO = save(empChangesAddDTO, tokenUser);

        // 是否走审批
        if (empChangesAddDTO.getApproFlowId() == null) {
            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
            empInfoUpdateDTO.setId(empChangesAddDTO.getEmpId());
            // 待离职
            empInfoUpdateDTO.setStatus(WAIT_QUIT.getValue());
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO.setChangeStatus(3);
            // 待审批
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
            empInfoService.update(empInfoUpdateDTO, tokenUser);
        } else {
            // 走离职审批
            String approFlowId = empChangesAddDTO.getApproFlowId();
            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
            empInfoUpdateDTO.setId(empChangesAddDTO.getEmpId());
            // 待离职
            empInfoUpdateDTO.setStatus(WAIT_QUIT.getValue());
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO.setChangeStatus(3);
            // 待审批
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_ING.getValue());

            // 发起离职审批
            UserApproVO userApproVO = approProviderService.createLeavingAppro(empInfoVO, empChangesVO, approFlowId, tokenUser);
            // 保存审批用的流程
            updateUserApproId(empChangesVO.getId(), userApproVO.getId(), userApproVO.getFlowId(), tokenUser);
            // 修改员工信息
            empInfoService.update(empInfoUpdateDTO, tokenUser);
            HrLogKit.logForSave("员工发起离职审批,员工姓名:" + empInfoVO.getName(), "leavePositionAppro",
                    userApproVO.getId(), companyDO.getId(), tokenUser);
        }
        HrLogKit.logForSave("员工申请离职,员工姓名:" + empInfoVO.getName(),
                "leavePosition", empInfoVO.getCompanyId(), companyDO.getId(), tokenUser);
        StringBuilder desc = new StringBuilder();
        desc.append(PersonalEventExample.INSERT_INTO_ADMIN).append(tokenUser.getUserName());
        desc.append(PersonalEventEnum.EXIT_PROCEDURE.getDesc()).append(",");
        Date preQuitDate = empChangesVO.getPreQuitDate() == null ? new Date() : empChangesVO.getPreQuitDate();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        desc.append(PersonalEventExample.INSERT_PRELEAVE).append(formatter.format(preQuitDate));
        if (StringUtils.isNoneEmpty(empChangesVO.getQuitReason())) {
            desc.append(PersonalEventExample.INSERT_LEAVE_REASON).append(empChangesVO.getQuitReason());
        }
        personalEventService.autoSave(empInfoVO, tokenUser, desc.toString(), PersonalEventEnum.EXIT_PROCEDURE.getValue()
                , PersonalEventEnum.EXIT_PROCEDURE.getDesc());

        return empChangesVO;
    }

    @Override
    public String leavePositionAndEntry(EmpChangeCompanyDTO empChangeCompanyDTO, TokenUser tokenUser) {
        ParamException.notNull(empChangeCompanyDTO.getCurrentCompanyId(), "要调入的公司Id不能为空");
        // 离职
        EmpInfoVO empInfoVO = empInfoService.selectById(empChangeCompanyDTO.getEmpId(), tokenUser.getSiteId());
        if (Objects.isNull(empInfoVO)) {
            return "待离职的员工不存在或已删除,请检查";
        }
        if (!empInfoVO.getChangeStatus().equals(0)) {
            return "员工正在进行其他操作,待其结束后再进行离职操作";
        }
        // 员工确认到岗先离职再入职 否则直接入职
        if (empInfoVO.getStatus() < EmpInfoStatus.HAS_QUIT.getValue()) {
            EmpChangesAddDTO empChangesAddDTO = new EmpChangesAddDTO();
            empChangesAddDTO.setCompanyId(empChangeCompanyDTO.getCompanyId());
            empChangesAddDTO.setEmpId(empChangeCompanyDTO.getEmpId());
            empChangesAddDTO.setChangeType(EmpChangeType.LEAVE.getValue());
            empChangesAddDTO.setPreQuitDate(empChangeCompanyDTO.getPreQuitDate() == null ? new Date() : empChangeCompanyDTO.getPreQuitDate());
            empChangesAddDTO.setQuitReason("其他");
            empChangesAddDTO.setQuitRemarks("更换公司");
            // 不需要审批,直接保存
            empChangesAddDTO.setApproFlowId(null);
            EmpChangesVO empChangesVO = leavePosition(empChangesAddDTO, tokenUser);
            // 确认离职
            confirmLeave(empChangesVO.getId(), tokenUser);
            //更换用工单位 离职通知
            sendNotice(empChangesVO.getEmpId(), empChangesVO.getCompanyId(), DateUtil.offsetMinute(new Date(), 1), NoticeConstants.RESIGN, tokenUser);
        }

        //删除员工记录
        OperationEmpRecordQuery operationEmpRecordQuery = new OperationEmpRecordQuery();
        operationEmpRecordQuery.setEmpId(empChangeCompanyDTO.getEmpId());
        List<OperationEmpRecordListVO> select = operationEmpRecordService.select(operationEmpRecordQuery, tokenUser.getSiteId());
        for (OperationEmpRecordListVO operationEmpRecordListVO : select) {
            operationEmpRecordService.deleteByIds(tokenUser, operationEmpRecordListVO.getId());
        }
        return null;
    }

    @Override
    public EmpChangesVO findByUserApproId(String userApproId, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("userApproFlowId", userApproId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        EmpChangesDO empChangesDO = empChangesDAO.selectOneByExample(example);
        if (Objects.isNull(empChangesDO)) {
            return null;
        }
        return empChangesDO.to(EmpChangesVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer confirmTransferPosition(String empChangesId, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(empChangesId, tokenUser.getSiteId());
        ParamException.notNull(empChangesVO, "员工变动记录不存在");

        // 要转的部门
        List<String> depIdList = new ArrayList<>();
        if (!StringUtils.isEmpty(empChangesVO.getCurrentDep())) {
            depIdList = Arrays.asList(empChangesVO.getCurrentDep().split(","));
        }
        // 要转的岗位
        List<String> positionIdList = new ArrayList<>();
        if (!StringUtils.isEmpty(empChangesVO.getCurrentPosition())) {
            positionIdList = Arrays.asList(empChangesVO.getCurrentPosition().split(","));
        }
        // 修改员工信息
        // 修改部门、岗位
        updateDepAndPositionInfo(empChangesVO, depIdList, positionIdList, tokenUser);

        // 主管,工作城市等
        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesVO.getEmpId());
        // 待审批
        empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(0);
        empInfoUpdateDTO.setSupervisor(empChangesVO.getCurrentSupervisor());
        empInfoUpdateDTO.setManagerForm(empChangesVO.getCurrentManagerForm());
        empInfoUpdateDTO.setWorkCityId(empChangesVO.getCurrentWorkCityId());
        empInfoService.update(empInfoUpdateDTO, tokenUser);

        // 修改申请状态
        Integer count = updateEmpChangeStatus(empChangesVO.getId(), tokenUser);
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
        //正式调岗
        personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, PersonalEventEnum.TRANSFER.getDesc(), PersonalEventEnum.TRANSFER.getValue(), PersonalEventEnum.TRANSFER.getDesc());
        CompanyDO companyDO = companyService.selectDOById(empInfoDO.getCompanyId(), tokenUser.getSiteId());
        HrLogKit.logForSave("员工确认调岗,员工姓名:" + empInfoDO.getName(),
                "confimTransferPosition", empChangesId, companyDO.getId(), tokenUser);
        return count;
    }

    @Override
    public Integer confirmTransferPositionByChangesId(String empChangesId, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(empChangesId, tokenUser.getSiteId());
        ParamException.notNull(empChangesVO, "申请不存在或已删除");

        String empId = empChangesVO.getEmpId();
        EmpInfoVO empInfoVO = empInfoService.selectById(empId, tokenUser.getSiteId());
        ParamException.notNull(empInfoVO, "员工不存在或已删除,请检查");
        if (!empInfoVO.getChangeStatus().equals(2)) {
            // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            throw new ParamException("员工状态不是调岗中,不需要确认");
        } else if (!empInfoVO.getApprovalStatus().equals(ApprovalStatusEnum.APPRO_SUCCESS.getValue())
                && !empInfoVO.getApprovalStatus().equals(ApprovalStatusEnum.APPRO_DISABLE.getValue())) {
            // 审批状态 审批通过或不需要审批
            throw new ParamException("申请尚未审核通过,不能确认");
        }
        return confirmTransferPosition(empChangesId, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer batchConfirmTransferPosition(String[] empIds, TokenUser tokenUser) {
        ParamException.notEmpty(empIds, "请选择确认调岗的人员");
        int count = 0;
        for (String empId : empIds) {
            // 查询变更记录
            String empChangesId = getLastChangesId(empId, EmpChangeType.TRANSFER__POSITION.getValue(),
                    tokenUser.getSiteId());
            // 根据变更记录id确认调岗
            confirmTransferPositionByChangesId(empChangesId, tokenUser);
            count++;
        }
        return count;
    }


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer updateEmpChangeStatus(String id, TokenUser tokenUser) {
        EmpChangesDO empChangesUp = new EmpChangesDO();
        empChangesUp.setId(id);
        empChangesUp.setChangeStatus(EmpChangeStatus.PASS.getValue());
        return updateByIdSelective(empChangesUp, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void revokeTransferPosition(String empChangesId, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(empChangesId, tokenUser.getSiteId());
        if (Objects.isNull(empChangesVO)) {
            return;
        }
        // 删除申请
        deleteByIds(tokenUser, empChangesId);
        // 员工恢复正常
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesVO.getEmpId());
        empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(0);
        empInfoService.update(empInfoUpdateDTO, tokenUser);
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
        String desc = "由管理员" + tokenUser.getUserName() + PersonalEventEnum.REVOKE_TRANSFER.getDesc() + "";

        personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, desc, PersonalEventEnum.REVOKE_TRANSFER.getValue(), PersonalEventEnum.REVOKE_TRANSFER.getDesc());
        CompanyDO companyDO = companyService.selectDOById(empInfoDO.getCompanyId(), tokenUser.getSiteId());
        HrLogKit.logForDelete("员工撤销调岗申请,员工姓名:" + empInfoDO.getName(),
                "revokeTransferPosition", companyDO.getId(), empChangesId, tokenUser);

    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer confirmLeave(String empChangesId, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(empChangesId, tokenUser.getSiteId());
        ParamException.notNull(empChangesVO, "员工变动记录不存在");

        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesVO.getEmpId());
        empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_QUIT.getValue());
        // 审批状态改为不需要审批
        empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(0);
        // 离职时间
        empInfoUpdateDTO.setLeaveDate(empChangesVO.getPreQuitDate());
        empInfoUpdateDTO.setLeaveReason(empChangesVO.getQuitReason());
        empInfoService.update(empInfoUpdateDTO, tokenUser);

        // 修改申请状态
        Integer count = updateEmpChangeStatus(empChangesVO.getId(), tokenUser);

        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
//        // 离职同时删除用户
//        if (Objects.nonNull(empInfoDO) && StringUtils.isNotEmpty(empInfoDO.getUserId())) {
//            String[] delIds = {empInfoDO.getUserId()};
//            userProviderService.dimissionUser(delIds, tokenUser);
//        }
        HrLogKit.logForSave("员工确认离职,员工姓名:" + empInfoDO.getName(),
                "confirmLeave", empInfoDO.getId(), empInfoDO.getCompanyId(), tokenUser);
        personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, PersonalEventEnum.EXIT.getDesc(),
                PersonalEventEnum.EXIT.getValue(), PersonalEventEnum.EXIT.getDesc());
        return count;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void revokeLeave(String empChangesId, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(empChangesId, tokenUser.getSiteId());
        if (Objects.isNull(empChangesVO)) {
            return;
        }
        // 员工恢复正常
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());
        empInfoUpdateDTO.setId(empChangesVO.getEmpId());
        empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(0);
        empInfoService.update(empInfoUpdateDTO, tokenUser);

        // 删除申请
        deleteByIds(tokenUser, empChangesId);
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
        String desc = "由管理员" + tokenUser.getUserName() + PersonalEventEnum.REVOKE_LEAVE.getDesc() + "";

        personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, desc,
                PersonalEventEnum.REVOKE_LEAVE.getValue(), PersonalEventEnum.REVOKE_LEAVE.getDesc());
        CompanyDO companyDO = companyService.selectDOById(empInfoDO.getCompanyId(), tokenUser.getSiteId());
        HrLogKit.logForDelete("员工撤销离职,员工姓名:" + empInfoDO.getName(),
                "revokeLeave", empChangesId, companyDO.getId(), tokenUser);
    }

    @Override
    public String getLastChangesId(String empId, Integer changeType, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("empId", empId)
                .andEqualTo("changeType", changeType)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();

        List<EmpChangesDO> empChangesDOList = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOList)) {
            return null;
        }
        return empChangesDOList.get(0).getId();
    }

    @Override
    public List<String> listTransferEmp(String companyId, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("changeType", EmpChangeType.TRANSFER__POSITION.getValue())
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();

        List<EmpChangesDO> empChangesList = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesList)) {
            return null;
        }
        return empChangesList.stream().map(EmpChangesDO::getEmpId).collect(Collectors.toList());
    }

    @Override
    public Page<EmpChangesRelationVO> pageEmpResignedList(String companyId, String empName, Integer pageNo, Integer pageSize, String siteId) {
        int changeType = EmpChangeType.LEAVE.getValue();
        // 离职
        com.github.pagehelper.Page<EmpChangesDO> page1 = PageHelper.startPage(pageNo, pageSize);
        List<EmpChangesDO> empChangesRelationVOList = empChangesDAO.pageEmpResignedList(companyId, empName, siteId, changeType, EmpChangeStatus.PASS.getValue());
        Page<EmpChangesDO> empChangesDoPage = new Page<EmpChangesDO>();
        empChangesDoPage.setEntities(empChangesRelationVOList);
        empChangesDoPage.setEntityCount((int) page1.getTotal());
        empChangesDoPage.setPageCount(page1.getPageNum());
        if (CollectionUtils.isEmpty(empChangesDoPage.getEntities())) {
            return new Page<>(pageSize, pageNo);
        }
        List<EmpChangesRelationVO> changesRelationVOList = empChangesDoListToVoList(empChangesDoPage.getEntities(), siteId);
        // 过滤掉错误信息 若得到条数变少 重新查询
        if (changesRelationVOList.size() < empChangesDoPage.getEntities().size()) {
            pageEmpRelation(companyId, changeType, pageNo, pageSize, siteId);
        }
        return new Page<>(changesRelationVOList, pageNo, pageSize
                , empChangesDoPage.getEntityCount());
    }

    @Override
    public List<EmpChangesRelationVO> empResignedList(EmpChangesQuery empChangesQuery, String siteId) {
        // 离职
        empChangesQuery.setChangeType(EmpChangeType.LEAVE.getValue());
        empChangesQuery.setChangeStatus(EmpChangeStatus.PASS.getValue());
        Example example = buildExample(empChangesQuery, siteId);
        List<EmpChangesDO> empChangesDOList = empChangesDAO.selectByExample(example);
        return empChangesDoListToVoList(empChangesDOList, siteId);
    }

    private List<EmpChangesRelationVO> empChangesDoListToVoList(List<EmpChangesDO> empChangesDOList, String siteId) {
        if (CollectionUtils.isEmpty(empChangesDOList)) {
            return new ArrayList<>();
        }
        return empChangesDOList.parallelStream().map(empChangesDO -> {
            EmpChangesRelationVO empChangesRelationVO = empChangesDO.to(EmpChangesRelationVO.class);
            EmpInfoListVO empInfoVO = empInfoService.selectEmpAndDepPositionById(empChangesRelationVO.getEmpId(), siteId);
            if (Objects.isNull(empInfoVO)) {
                // 员工不存在 删除离职记录并从列表里删除
                deleteByIds(siteId, SYSTEM_SUBJECT_TYPE, empChangesDO.getId());
                return null;
            }
            empChangesRelationVO.setEmpName(empInfoVO.getName());
            empChangesRelationVO.setPhone(empInfoVO.getPhone());
            empChangesRelationVO.setStatus(empInfoVO.getStatus());
            empChangesRelationVO.setDepName(empInfoVO.getDepName());
            empChangesRelationVO.setPositionName(empInfoVO.getPositionName());
            empChangesRelationVO.setLeaveDate(empInfoVO.getLeaveDate());
            return empChangesRelationVO;
        }).filter(Objects::nonNull).parallel().collect(Collectors.toList());
    }

    /**
     * 分页查询员工操作记录
     *
     * @param companyId  公司Id
     * @param changeType 操作类型
     * @param pageNo     页码
     * @param pageSize   页面大小
     * @param siteId     站点Id
     * @return 员工操作记录
     */
    private Page<EmpChangesRelationVO> pageEmpRelation(String companyId, Integer changeType, Integer pageNo, Integer pageSize, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", siteId)
                .andEqualTo("changeType", changeType)
                .andEqualTo("changeStatus", EmpChangeStatus.PASS.getValue());
        example.orderBy("quitDate").desc();
        Page<EmpChangesDO> empChangesDoPage = empChangesDAO.selectPageByExample(example, pageNo, pageSize);
        if (CollectionUtils.isEmpty(empChangesDoPage.getEntities())) {
            return new Page<>(pageSize, pageNo);
        }
        List<EmpChangesRelationVO> changesRelationVOList = empChangesDoListToVoList(empChangesDoPage.getEntities(), siteId);
        // 过滤掉错误信息 若得到条数变少 重新查询
        if (changesRelationVOList.size() < empChangesDoPage.getEntities().size()) {
            pageEmpRelation(companyId, changeType, pageNo, pageSize, siteId);
        }
        return new Page<>(changesRelationVOList, empChangesDoPage.getPageNo(), empChangesDoPage.getPageSize()
                , empChangesDoPage.getEntityCount());
    }

    @Override
    public Page<EmpChangesRelationVO> pageEmpTransferList(String companyId, String empName, Integer pageNo, Integer pageSize, String siteId) {
        // 调岗
        int changeType = EmpChangeType.TRANSFER__POSITION.getValue();
        com.github.pagehelper.Page<EmpChangesDO> page1 = PageHelper.startPage(pageNo, pageSize);
        List<EmpChangesDO> empChangesRelationVOList = empChangesDAO.pageEmpResignedList(companyId, empName, siteId, changeType, EmpChangeStatus.PASS.getValue());
        Page<EmpChangesDO> empChangesDoPage = new Page<EmpChangesDO>();
        empChangesDoPage.setEntities(empChangesRelationVOList);
        empChangesDoPage.setEntityCount((int) page1.getTotal());
        empChangesDoPage.setPageCount(page1.getPageNum());
        if (CollectionUtils.isEmpty(empChangesDoPage.getEntities())) {
            return new Page<>(pageSize, pageNo);
        }
        List<EmpChangesRelationVO> changesRelationVOList = empChangesDoListToVoList(empChangesDoPage.getEntities(), siteId);
        // 过滤掉错误信息 若得到条数变少 重新查询
        if (changesRelationVOList.size() < empChangesDoPage.getEntities().size()) {
            pageEmpRelation(companyId, changeType, pageNo, pageSize, siteId);
        }
        return new Page<>(changesRelationVOList, pageNo, pageSize
                , empChangesDoPage.getEntityCount());
    }

    @Override
    public List<EmpChangesRelationVO> empTransferList(EmpChangesQuery empChangesQuery, String siteId) {
        // 调岗
        empChangesQuery.setChangeType(EmpChangeType.TRANSFER__POSITION.getValue());
        empChangesQuery.setChangeStatus(EmpChangeStatus.PASS.getValue());
        Example example = buildExample(empChangesQuery, siteId);
        List<EmpChangesDO> list = empChangesDAO.selectByExample(example);
        return empChangesDoListToVoList(list, siteId);
    }

    @Override
    public Integer deleteByEmpIds(List<String> empIds, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empIds)) {
            return 0;
        }
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("empId", empIds);
        List<EmpChangesDO> empChangesDOList = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOList)) {
            return 0;
        }

        return deleteByIds(tokenUser, empChangesDOList.parallelStream().map(EmpChangesDO::getId).toArray(String[]::new));
    }

    @Override
    public List<EmpChangesDO> selectLeaveByCompanyIdAndEmpId(String companyId, String empId) {
        ParamException.hasText(companyId, "公司Id不能为空");
        ParamException.hasText(empId, "员工Id不能为空");
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("companyId", companyId)
                .andEqualTo("changeType", EmpChangeType.LEAVE.getValue());
        return empChangesDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<ConfirmLeaveOfficeListVO> checkAndConfirmLeaveOffice(ConfirmLeaveOfficeDTO confirmLeaveOfficeDTO, TokenUser tokenUser) {
        EmpChangesVO empChangesVO = selectById(confirmLeaveOfficeDTO.getEmpChangesId(), tokenUser.getSiteId());
        if (Objects.isNull(empChangesVO)) {
            throw new ParamException("离职申请不存在或已删除");
        } else {
            String empId = empChangesVO.getEmpId();
            EmpInfoVO empInfoVO = empInfoService.selectById(empId, tokenUser.getSiteId());
            if (Objects.isNull(empInfoVO)) {
                throw new ParamException("离职员工不存在或已删除,请检查");
            } else if (!empInfoVO.getChangeStatus().equals(3)) {
                // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                throw new ParamException("离职员工状态不是离职中,不需要确认");
            } else if (!empInfoVO.getApprovalStatus().equals(ApprovalStatusEnum.APPRO_SUCCESS.getValue())
                    && !empInfoVO.getApprovalStatus().equals(ApprovalStatusEnum.APPRO_DISABLE.getValue())) {
                // 审批状态 审批通过或不需要审批
                throw new ParamException("申请尚未审核通过,不能确认");
            }
            ConfirmLeaveVO confirmLeave = confirmLeaveOffice(confirmLeaveOfficeDTO, tokenUser);
            CheckDecreaseFailVO checkDecrease = confirmLeave.getCheckDecrease();
            EmpInfoDO empInfo = confirmLeave.getEmpInfo();
            ConfirmLeaveOfficeListVO confirmLeaveOfficeListVO = new ConfirmLeaveOfficeListVO();
            confirmLeaveOfficeListVO.setEmpId(empInfo.getId());
            confirmLeaveOfficeListVO.setEmpName(empInfo.getName());
            confirmLeaveOfficeListVO.setConfirmLeaveDate(confirmLeaveOfficeDTO.getConfirmLeaveOfficeDate());
            confirmLeaveOfficeListVO.setIdCard(empInfo.getIdCard());
            confirmLeaveOfficeListVO.setPositionName(empInfo.getPositionName());
            confirmLeaveOfficeListVO.setDepName(empInfo.getDepName());
            confirmLeaveOfficeListVO.setPhone(empInfo.getPhone());
            confirmLeaveOfficeListVO.setSocDescription(checkDecrease.getSocDescription());
            confirmLeaveOfficeListVO.setMeDescription(checkDecrease.getMeDescription());
            confirmLeaveOfficeListVO.setPfDescription(checkDecrease.getPfDescription());
            confirmLeaveOfficeListVO.setSchemeName(checkDecrease.getSchemeName());
            confirmLeaveOfficeListVO.setSocCityName(checkDecrease.getSocCityName());
            return Collections.singletonList(confirmLeaveOfficeListVO);
        }
    }

    @Override
    public List<ConfirmLeaveOfficeListVO> checkAndConfirmLeaveOfficeBatch(ConfirmLeaveOfficeDTO confirmLeaveOfficeDTO, TokenUser tokenUser) {
        List<ConfirmLeaveOfficeListVO> confirmLeaveOfficeListVOList = new ArrayList<>();
        List<String> empIds = confirmLeaveOfficeDTO.getEmpIds();
        if (CollectionUtils.isEmpty(empIds)) {
            throw new ParamException("没有选择需要离职的员工，请检查是否选择");
        }
        // 构造查询参数
        List<String> empChangesIds = new ArrayList<>();
        for (String empId : empIds) {
            String empChangesId = this.getLastChangesId(empId, EmpChangeType.LEAVE.getValue(), tokenUser.getSiteId());
            if (org.springframework.util.StringUtils.isEmpty(empChangesId)) {
                // 查询不到跳过
                continue;
            }
            empChangesIds.add(empChangesId);
        }
        if (CollectionUtils.isEmpty(empChangesIds)) {
            throw new ParamException("暂无员工离职申请,无法确认");
        }
        if (confirmLeaveOfficeDTO.getWhetherDecrease() == null) {
            confirmLeaveOfficeDTO.setWhetherDecrease(false);
        }
        if (confirmLeaveOfficeDTO.getWhetherLaunchedContract() == null) {
            confirmLeaveOfficeDTO.setWhetherLaunchedContract(false);
        }
        if (confirmLeaveOfficeDTO.getWhetherLaunchedContract() == null) {
            confirmLeaveOfficeDTO.setWhetherLaunchedContract(false);
        }
        for (String empChangesId : empChangesIds) {
            confirmLeaveOfficeDTO.setEmpChangesId(empChangesId);
            List<ConfirmLeaveOfficeListVO> confirmLeaveOfficeListVOS = checkAndConfirmLeaveOffice(confirmLeaveOfficeDTO, tokenUser);
            if (CollectionUtils.isEmpty(confirmLeaveOfficeListVOS)) {
                continue;
            }
            confirmLeaveOfficeListVOList.addAll(confirmLeaveOfficeListVOS);
        }
        return confirmLeaveOfficeListVOList;
    }

    /**
     * (批量)确认离职方法调用
     */
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public ConfirmLeaveVO confirmLeaveOffice(ConfirmLeaveOfficeDTO confirmLeaveOfficeDTO, TokenUser tokenUser) {
        String confirmSocBySite = empSocInfoExtraService.getConfirmSocBySite(tokenUser);
        String dateStr = DateUtils.getYearMonthStr(confirmLeaveOfficeDTO.getConfirmLeaveOfficeDate());
        ConfirmLeaveVO confirmLeave = new ConfirmLeaveVO();
        CheckDecreaseFailVO checkDecrease = new CheckDecreaseFailVO();
        EmpChangesVO empChangesVO = selectById(confirmLeaveOfficeDTO.getEmpChangesId(), tokenUser.getSiteId());
        if (Objects.isNull(empChangesVO)) {
            return null;
        }
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empChangesVO.getEmpId(), tokenUser.getSiteId());
        confirmLeave.setEmpInfo(empInfoDO);
        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empChangesVO.getEmpId());
        // 审批状态改为不需要审批
        empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
        // 需要签合同的时候这条员工变动记录要卡在这,合同签完了才能进已离职记录
        if (confirmLeaveOfficeDTO.getWhetherLaunchedContract()) {
            // 需要签合同的话,员工变动状态为3（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
            empInfoUpdateDTO.setChangeStatus(3);
        } else {
            // 如果该人员是预登记人员  则预登记人员状态改为已离职
            CheckInPeopleDO checkInPeopleDO = checkInPeopleService.selectByPhone(empInfoDO.getPhone(), tokenUser.getSiteId());
            if (Objects.nonNull(checkInPeopleDO)) {
                // 修改该人员的状态
                CheckInPeopleUpdateDTO checkInPeopleUpdateDTO = new CheckInPeopleUpdateDTO();
                checkInPeopleUpdateDTO.setId(checkInPeopleDO.getId());
                checkInPeopleUpdateDTO.setWorkStatus(CheckInPeopleConstant.WORK_STATUS_DIMISSION);
                checkInPeopleUpdateDTO.setStatus(CheckInPeopleConstant.STATUS_DIMISSION);
                checkInPeopleService.update(checkInPeopleUpdateDTO, tokenUser);
            }
            // 不需要签合同的话修改员工变动状态为当前无变动,员工状态变为已离职
            empInfoUpdateDTO.setChangeStatus(0);
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_QUIT.getValue());
            // 修改申请状态改为通过
            updateEmpChangeStatus(empChangesVO.getId(), tokenUser);
//            // 离职同时删除用户
//            if (StringUtils.isNotEmpty(empInfoDO.getUserId())) {
//                String[] delIds = {empInfoDO.getUserId()};
//                userProviderService.dimissionUser(delIds, tokenUser);
//            }
        }

        // 离职时间
        empInfoUpdateDTO.setLeaveDate(confirmLeaveOfficeDTO.getConfirmLeaveOfficeDate());
        // 离职原因
        empInfoUpdateDTO.setLeaveReason(empChangesVO.getQuitReason());
        empInfoService.update(empInfoUpdateDTO, tokenUser);
        // 判断是否进行社保减员
        if (confirmLeaveOfficeDTO.getWhetherDecrease()) {
            IncreaseDecreaseQuery increaseDecreaseQuery = new IncreaseDecreaseQuery();
            increaseDecreaseQuery.setServiceCost(confirmLeaveOfficeDTO.getServiceCost());
            if (confirmLeaveOfficeDTO.getWhetherSocDecrease()) {
                increaseDecreaseQuery.setStopSoc(true);
                increaseDecreaseQuery.setPlanStopSocYear(confirmLeaveOfficeDTO.getStopSocYear());
                increaseDecreaseQuery.setPlanStopSocMonth(confirmLeaveOfficeDTO.getStopSocMonth());
            } else {
                increaseDecreaseQuery.setStopSoc(false);
            }
            if (confirmLeaveOfficeDTO.getWhetherMeDecrease()) {
                increaseDecreaseQuery.setStopMe(true);
                increaseDecreaseQuery.setPlanStopMeYear(confirmLeaveOfficeDTO.getStopMeYear());
                increaseDecreaseQuery.setPlanStopMeMonth(confirmLeaveOfficeDTO.getStopMeMonth());
            } else {
                increaseDecreaseQuery.setStopMe(false);
            }
            if (confirmLeaveOfficeDTO.getWhetherPfDecrease()) {
                increaseDecreaseQuery.setStopPf(true);
                increaseDecreaseQuery.setSealedDateYear(confirmLeaveOfficeDTO.getSealedDateYear());
                increaseDecreaseQuery.setSealedDateMonth(confirmLeaveOfficeDTO.getSealedDateMonth());
            } else {
                increaseDecreaseQuery.setStopPf(false);
            }
            increaseDecreaseQuery.setEmpIdList(Collections.singletonList(empChangesVO.getEmpId()));
            increaseDecreaseQuery.setCompanyId(confirmLeaveOfficeDTO.getCompanyId());
            List<CheckDecreaseFailVO> decreaseList;
            if (NO_CONFIRM.equals(confirmSocBySite)) {
                decreaseList = empSocPlanService.decrease(increaseDecreaseQuery, tokenUser);
            } else {
                decreaseList = empSocInfoExtraService.decreaseExtra(increaseDecreaseQuery, tokenUser);
            }

            if (!CollectionUtils.isEmpty(decreaseList)) {
                checkDecrease = decreaseList.get(0);
            }
        } else {
            // 不社保减员的话没有走减员接口需要手动把参保管理里面的减员状态修改
            List<String> monthIdList = empSocMonthService.selectMonthIdListAfterAndEqualsDate
                    (confirmLeaveOfficeDTO.getCompanyId(), dateStr, tokenUser.getSiteId());
            empSocInfoService.updateWhetherLeave(Collections.singletonList(empChangesVO.getEmpId()),
                    true, monthIdList, tokenUser);
        }
        confirmLeave.setCheckDecrease(checkDecrease);
        // log日志
        HrLogKit.logForSave("员工确认离职,员工姓名:" + empInfoDO.getName(),
                "confimLeave", empInfoDO.getId(), empInfoDO.getCompanyId(), tokenUser);

        //操作记录
        OperationEmpRecordQuery operationEmpRecordQuery = new OperationEmpRecordQuery();
        operationEmpRecordQuery.setEmpId(empInfoDO.getId());
        List<OperationEmpRecordListVO> select = operationEmpRecordService.select(operationEmpRecordQuery, tokenUser.getSiteId());
        for (OperationEmpRecordListVO operationEmpRecordListVO : select) {
            OperationEmpRecordUpdateDTO operationEmpRecordUpdateDTO = new OperationEmpRecordUpdateDTO();
            operationEmpRecordUpdateDTO.setId(operationEmpRecordListVO.getId());
            operationEmpRecordUpdateDTO.setEmpStatus(4);
            operationEmpRecordService.update(operationEmpRecordUpdateDTO, tokenUser);
        }
        // 用工档案
        personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, PersonalEventEnum.EXIT.getDesc(),
                PersonalEventEnum.EXIT.getValue(), PersonalEventEnum.EXIT.getDesc());
        // 确认离职发通知
        sendNotice(empInfoDO.getId(), empInfoDO.getCompanyId(), confirmLeaveOfficeDTO.getConfirmLeaveOfficeDate(), NoticeConstants.RESIGN, tokenUser);
        return confirmLeave;
    }

    @Override
    public String exportErrorList(ImportExcelResultListVO<EmpChangeImportDTO> errorList, TokenUser tokenUser) {
        return ExcelKit.exportExcel("confirmLeaveError", "错误列表",
                EmpChangeImportDTO.class, errorList.getErrorList());
    }


    @Override
    public ImportExcelResultListVO<EmpChangeImportDTO> importEmpChangeFile(File file, String companyId, TokenUser tokenUser) {
        EmpChangeImportListener empChangeImportListener = new EmpChangeImportListener();
        empChangeImportListener.setCompanyId(companyId);
        empChangeImportListener.setTokenUser(tokenUser);
        empChangeImportListener.setParseOnly(false);
        // 读取excel
        EasyExcel.read(file, EmpChangeImportDTO.class, empChangeImportListener).sheet().doRead();
        ImportExcelResultListVO<EmpChangeImportDTO> result = new ImportExcelResultListVO<>();
        int allCount = empChangeImportListener.getDataList().size();
        result.setAllCount(allCount);
        int errorCount = empChangeImportListener.getErrorList().size();
        result.setErrorCount(errorCount);
        result.setSuccessCount(allCount - errorCount);
        result.setErrorList(empChangeImportListener.getErrorList());
        return result;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void confirmLeaveOfficeImportSaveDate(List<EmpChangeImportDTO> dataList, String companyId,
                                                 Map<String, EmpInfoDO> idCardEmpMap, TokenUser tokenUser) {
        String confirmSocBySite = empSocInfoExtraService.getConfirmSocBySite(tokenUser);
        List<String> empIdList = new ArrayList<>();
        for (EmpChangeImportDTO empChangeImportDTO : dataList) {
            EmpInfoDO empInfoDO = idCardEmpMap.get(empChangeImportDTO.getIdCard());
            // 3 离职中
            if (empInfoDO.getChangeStatus() == 3) {
                throw new ParamException("员工" + empInfoDO.getName() + "正在离职中,请勿重复操作");
            }
            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
            empInfoUpdateDTO.setId(empInfoDO.getId());
            EmpChangesAddDTO empChangesAddDTO = new EmpChangesAddDTO();
            // 离职原因
            empChangesAddDTO.setQuitReason(empChangeImportDTO.getLeaveOfficeReason());
            empChangesAddDTO.setChangeType(EmpChangeType.LEAVE.getValue());
            empChangesAddDTO.setEmpId(empInfoDO.getId());
            empChangesAddDTO.setCompanyId(companyId);
            // 离职时间
            Date leaveOfficeDate = DateKit8.parseDate(empChangeImportDTO.getLeaveOfficeDate());
            String dateStr = DateUtils.getYearMonthStr(leaveOfficeDate);
            empChangesAddDTO.setQuitDate(leaveOfficeDate);
            // 审批状态改为不需要审批
            empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
            // 修改员工变动状态为当前无变动,员工状态变为已离职
            empInfoUpdateDTO.setChangeStatus(0);
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_QUIT.getValue());
            // 修改申请状态改为通过
            empChangesAddDTO.setChangeStatus(EmpChangeStatus.PASS.getValue());
//            // 离职同时删除用户
//            if (StringUtils.isNotEmpty(empInfoDO.getUserId())) {
//                String[] delIds = {empInfoDO.getUserId()};
//                userProviderService.dimissionUser(delIds, tokenUser);
//            }
            // 离职时间
            empChangesAddDTO.setQuitDate(leaveOfficeDate);
            empInfoUpdateDTO.setLeaveDate(leaveOfficeDate);
            EmpChangesVO save = save(empChangesAddDTO, tokenUser);
            empIdList.add(save.getEmpId());
            // 离职原因
            empInfoUpdateDTO.setLeaveReason(empChangeImportDTO.getLeaveOfficeReason());
            empInfoService.update(empInfoUpdateDTO, tokenUser);
            IncreaseDecreaseQuery increaseDecreaseQuery = new IncreaseDecreaseQuery();
            if (empChangeImportDTO.getWhetherSocDecrease()) {
                String stopSocDate = empChangeImportDTO.getStopSocDate();
                String[] stopSocYearAndMonth = DateUtils.getYearAndMonthByDateString(stopSocDate);
                increaseDecreaseQuery.setStopSoc(true);
                increaseDecreaseQuery.setPlanStopSocYear(stopSocYearAndMonth[0]);
                increaseDecreaseQuery.setPlanStopSocMonth(stopSocYearAndMonth[1]);
            } else {
                increaseDecreaseQuery.setStopSoc(false);
            }
            if (empChangeImportDTO.getWhetherMeDecrease()) {
                String stopMeDate = empChangeImportDTO.getStopMeDate();
                String[] stopMeYearAndMonth = DateUtils.getYearAndMonthByDateString(stopMeDate);
                increaseDecreaseQuery.setStopMe(true);
                increaseDecreaseQuery.setPlanStopMeYear(stopMeYearAndMonth[0]);
                increaseDecreaseQuery.setPlanStopMeMonth(stopMeYearAndMonth[1]);
            } else {
                increaseDecreaseQuery.setStopMe(false);
            }
            if (empChangeImportDTO.getWhetherSealed()) {
                String sealedDate = empChangeImportDTO.getSealedDate();
                String[] sealedYearAndMonth = DateUtils.getYearAndMonthByDateString(sealedDate);
                increaseDecreaseQuery.setStopPf(true);
                increaseDecreaseQuery.setSealedDateYear(sealedYearAndMonth[0]);
                increaseDecreaseQuery.setSealedDateMonth(sealedYearAndMonth[1]);
            } else {
                increaseDecreaseQuery.setStopPf(false);
            }
            increaseDecreaseQuery.setEmpIdList(Collections.singletonList(empInfoDO.getId()));
            increaseDecreaseQuery.setCompanyId(companyId);
            if (!StringUtils.isEmpty(empChangeImportDTO.getServiceCost())) {
                increaseDecreaseQuery.setServiceCost(new BigDecimal(empChangeImportDTO.getServiceCost()));
            }
            if (NO_CONFIRM.equals(confirmSocBySite)) {
                empSocPlanService.decrease(increaseDecreaseQuery, tokenUser);
            } else {
                empSocInfoExtraService.decreaseExtra(increaseDecreaseQuery, tokenUser);
            }
            if(!increaseDecreaseQuery.getStopSoc() && !increaseDecreaseQuery.getStopMe()
                    && !increaseDecreaseQuery.getStopPf()){
                // 不社保减员的话没有走减员接口需要手动把参保管理里面的减员状态修改
                List<String> monthIdList = empSocMonthService.selectMonthIdListAfterAndEqualsDate
                        (companyId, dateStr, tokenUser.getSiteId());
                empSocInfoService.updateWhetherLeave(Collections.singletonList(empInfoDO.getId()),
                        true, monthIdList, tokenUser);
            }
            // log日志
            HrLogKit.logForSave("员工确认离职,员工姓名:" + empInfoDO.getName(), "confirmLeave",
                    empInfoDO.getId(), empInfoDO.getCompanyId(), tokenUser);
            // 用工档案
            personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class), tokenUser, PersonalEventEnum.EXIT.getDesc(),
                    PersonalEventEnum.EXIT.getValue(), PersonalEventEnum.EXIT.getDesc());

            // 如果该人员是预登记人员  则预登记人员状态改为已离职
            CheckInPeopleDO checkInPeopleDO = checkInPeopleService.selectByPhone(empInfoDO.getPhone(), tokenUser.getSiteId());
            if (Objects.nonNull(checkInPeopleDO)) {
                // 修改该人员的状态
                CheckInPeopleUpdateDTO checkInPeopleUpdateDTO = new CheckInPeopleUpdateDTO();
                checkInPeopleUpdateDTO.setId(checkInPeopleDO.getId());
                checkInPeopleUpdateDTO.setWorkStatus(CheckInPeopleConstant.WORK_STATUS_DIMISSION);
                checkInPeopleUpdateDTO.setStatus(CheckInPeopleConstant.STATUS_DIMISSION);
                checkInPeopleService.update(checkInPeopleUpdateDTO, tokenUser);
            }
        }

        // 发送离职通知
        String subjectId = empIdList.stream().map(String::valueOf).collect(Collectors.joining(","));
        sendNotice(subjectId, companyId, DateUtil.offsetMinute(new Date(), 1), NoticeConstants.RESIGN, tokenUser);
    }

    @Override
    public EmpChangesDO selectLastResign(String empId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("changeType", EmpChangeType.LEAVE.getValue())
                .andGreaterThan("preQuitDate", DateKit8.getCurrentDay(DateKit8.DATE));
        example.orderBy("gmtCreate").desc();
        List<EmpChangesDO> empChangesDOS = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOS)) {
            return null;
        }
        return empChangesDOS.get(0);
    }

    @Override
    public EmpChangesDO selectLastTransfer(String empId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("changeType", EmpChangeType.TRANSFER__POSITION.getValue())
                .andGreaterThan("adjustmentDate", DateKit8.getCurrentDay(DateKit8.DATE));
        example.orderBy("gmtCreate").desc();
        List<EmpChangesDO> empChangesDOS = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOS)) {
            return null;
        }
        return empChangesDOS.get(0);
    }

    @Override
    public EmpChangesDO selectResignByEmpId(String empId, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("changeType", EmpChangeType.LEAVE.getValue());
        List<EmpChangesDO> empChangesDOS = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOS)) {
            return null;
        }
        return empChangesDOS.get(0);
    }

    @Override
    public EmpChangesDO selectTransferByEmpId(String empId, String siteId) {
        Example example = new Example(EmpChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("changeType", EmpChangeType.TRANSFER__POSITION.getValue())
                .andEqualTo("changeStatus", EmpChangeStatus.INIT.getValue());
        List<EmpChangesDO> empChangesDOS = empChangesDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empChangesDOS)) {
            return null;
        }
        return empChangesDOS.get(0);
    }

}




